package entities;

import java.io.Serializable;

/**
 * ScheduleDate
 * Contains date information relevant to TimeEdit in a more easily
 * accessible way.
 * @author Mattias
 *
 */
public class ScheduleDate implements Comparable<ScheduleDate>, Serializable{
	private int day;
	private int month;
	private int year;
	private int week;
	private String weekDay;
	private String monthString;
	private String dayMonthString;
	private String weekString;
	public static final long serialVersionUID = 223L;
	
	/**
	 * Creates the ScheduleDate object.
	 * @param weekYear form: form: Vecka WW, YYYY (i.e Vecka 15, 1984)
	 * @param uglyDayMonth form: form: DD MMM or D MMM (i.e 23 okt)
	 * @param weekDay form: WdWdWd (e.e Tor)
	 */
	public ScheduleDate(String weekYear, String uglyDayMonth, String weekDay)
	{
		this.fixWeekDay(weekDay);
		this.fixMonth(uglyDayMonth);
		this.fixDay(uglyDayMonth);
		this.dayMonthString=this.monthString + " " + this.day;
		this.fixWeekAndYear(weekYear);
	}

	/**
	 * Turn 3 letter Swedish weekday into full name English weekday :D
	 * @param weekDay
	 */
	private void fixWeekDay(String weekDay){
		switch(weekDay.toCharArray()[0])
		{
		case 'M':
			this.weekDay="Monday";
			break;
		case 'T':
			if(weekDay.equals("Tis")){
				this.weekDay="Tuesday";
			}else{
				this.weekDay="Thursday";
			}
			break;
		case 'O':
			this.weekDay="Wednesday";
			break;
		case 'F':
			this.weekDay="Friday";
			break;
		case 'L':
			this.weekDay="Saturday";
			break;
		case 'S':
			this.weekDay="Sunday";
			break;
		}
	}
	
	
	/**
	 * Turns TE DD MMM format into proper month String and month int.
	 * @param uglyDayMonth
	 */
	private void fixMonth(String uglyDayMonth){
		if(uglyDayMonth.contains("jan"))
			this.month=1;
		else if(uglyDayMonth.contains("feb"))
			this.month=2;
		else if(uglyDayMonth.contains("mar"))
			this.month=3;
		else if(uglyDayMonth.contains("apr"))
			this.month=4;
		else if(uglyDayMonth.contains("maj"))
			this.month=5;
		else if(uglyDayMonth.contains("jun"))
			this.month=6;
		else if(uglyDayMonth.contains("jul"))
			this.month=7;
		else if(uglyDayMonth.contains("aug"))
			this.month=8;
		else if(uglyDayMonth.contains("sep"))
			this.month=9;
		else if(uglyDayMonth.contains("okt"))
			this.month=10;
		else if(uglyDayMonth.contains("nov"))
			this.month=11;
		else if(uglyDayMonth.contains("dec"))
			this.month=12;

		switch(this.month)
		{
		case 1: this.monthString="January"; break;
		case 2: this.monthString="February"; break;
		case 3: this.monthString="Mars"; break;
		case 4: this.monthString="April"; break;
		case 5: this.monthString="May"; break;
		case 6: this.monthString="June"; break;
		case 7: this.monthString="July"; break;
		case 8: this.monthString="August"; break;
		case 9: this.monthString="September"; break;
		case 10: this.monthString="October"; break;
		case 11: this.monthString="November"; break;
		case 12: this.monthString="December"; break;
		}
		}
	
	/**
	 * Turns the TE DD MMM format into a proper date.
	 * @param uglyDayMonth
	 */
	private void fixDay(String uglyDayMonth) {
		String onlyDate=uglyDayMonth.substring(0, 2).trim();
		this.day=Integer.parseInt(onlyDate);
	}
	
	/**
	 * Turns TE Vecka WW, YYYY format into proper week & year
	 * @param weekYear
	 */
	private void fixWeekAndYear(String weekYear){
		String[] way = weekYear.split(",\\s*");
		this.year=Integer.parseInt(way[1]);
		this.weekString=way[0].replace("Vecka", "Week");
		this.week=Integer.parseInt(weekYear.replace(',', ' ').substring(6, 9).trim());
		
	}
	
	/**
	 * Turns TE WdWdWd format into proper weekday String and returns it.
	 * @param weekDay
	 * @return Weekday, or error if there is something wrong with the input.
	 */
	public static String getPrettyWeekDay(String weekDay){
		switch(weekDay.toCharArray()[0])
		{
		case 'M':
			return "Monday";
		case 'T':
			if(weekDay.equals("Tis")){
				return "Tuesday";
			}else{
				return "Thursday";
			}
		case 'O':
			return "Wednesday";
		case 'F':
			return "Friday";
		case 'L':
			return "Saturday";
		case 'S':
			return "Sunday";
		default:
			return "error";
		}
	}
	
	
	/**
	 * Turns TE DD MMM format into proper month String and returns it.
	 * @param uglyDayMonth
	 * @return monthString, or "error parsing month" if there is something wrong with the input string
	 */
	public static String getPrettyMonth(String uglyDayMonth){
		int month=0;
		if(uglyDayMonth.contains("jan"))
			month=1;
		else if(uglyDayMonth.contains("feb"))
			month=2;
		else if(uglyDayMonth.contains("mar"))
			month=3;
		else if(uglyDayMonth.contains("apr"))
			month=4;
		else if(uglyDayMonth.contains("maj"))
			month=5;
		else if(uglyDayMonth.contains("jun"))
			month=6;
		else if(uglyDayMonth.contains("jul"))
			month=7;
		else if(uglyDayMonth.contains("aug"))
			month=8;
		else if(uglyDayMonth.contains("sep"))
			month=9;
		else if(uglyDayMonth.contains("okt"))
			month=10;
		else if(uglyDayMonth.contains("nov"))
			month=11;
		else if(uglyDayMonth.contains("dec"))
			month=12;
			

		switch(month)
		{
		case 1: return "January";
		case 2: return "February";
		case 3: return "Mars";
		case 4: return "April";
		case 5: return "May";
		case 6: return "June";
		case 7: return "July";
		case 8: return "August";
		case 9: return "September";
		case 10: return "October";
		case 11: return "November";
		case 12: return "December";
		default: return "error parsing month";
		}
		
		}
	
	
	/**
	 * Turns TE DD MMM format into proper month int and returns it.
	 * @param uglyDayMonth
	 * @return  monthNumber, or -1 if there is something wrong with the input string
	 */
	public static int getIntMonth(String uglyDayMonth){
		
		if(uglyDayMonth.contains("jan"))
			return 1;
		else if(uglyDayMonth.contains("feb"))
			return 2;
		else if(uglyDayMonth.contains("mar"))
			return 3;
		else if(uglyDayMonth.contains("apr"))
			return 4;
		else if(uglyDayMonth.contains("maj"))
			return 5;
		else if(uglyDayMonth.contains("jun"))
			return 6;
		else if(uglyDayMonth.contains("jul"))
			return 7;
		else if(uglyDayMonth.contains("aug"))
			return 8;
		else if(uglyDayMonth.contains("sep"))
			return 9;
		else if(uglyDayMonth.contains("okt"))
			return 10;
		else if(uglyDayMonth.contains("nov"))
			return 11;
		else if(uglyDayMonth.contains("dec"))
			return 12;
		else
			return -1;
	}
	
/**
 * Turns TE DD MMM format into proper date int and returns it.
 * @param uglyDayMonth
 * @return the date
 */
	public static int getIntDay(String uglyDayMonth) {
		String onlyDate=uglyDayMonth.substring(0, 3).trim();
		return Integer.parseInt(onlyDate);
	}
	
	/**
	 * Turns TimeEdit swedish week-year format to english
	 * @param weekYear
	 * @return
	 */
	public static String getWeekAndYearString(String weekYear){
		return weekYear.replace("Vecka", "Week");		
	}
	
	public static int getIntYear(String weekYear){
		String[] way = weekYear.split(",\\s*");
		return Integer.parseInt(way[1]);
	}
	
	
	
	public int compareTo(ScheduleDate another) {
		if(another.year<this.year){
			return -1;
		}
		if(another.year==this.year && another.month<this.month){
			return -1;
		}
		if(another.year==this.year && another.month==this.month && another.day<this.day){
			return -1;
		}
		if(another.year>this.year){
			return -1;
		}
		if(another.year==this.year && another.month>this.month){
			return -1;
		}
		if(another.year==this.year && another.month==this.month && another.day>this.day){
			return -1;
		}
		return 0;
	}

	@Override
	public String toString() {
		return "ScheduleDate [" + weekDay + ", " + weekString + ", " + dayMonthString + ", "+ year + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + day;
		result = prime * result + month;
		result = prime * result + week;
		result = prime * result + year;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ScheduleDate other = (ScheduleDate) obj;
		if (day != other.day)
			return false;
		if (month != other.month)
			return false;
		if (week != other.week)
			return false;
		if (year != other.year)
			return false;
		return true;
	}

	public int getDay() {
		return day;
	}

	public void setDay(int day) {
		this.day = day;
	}

	public int getMonth() {
		return month;
	}

	public void setMonth(int month) {
		this.month = month;
	}

	public int getYear() {
		return year;
	}

	public void setYear(int year) {
		this.year = year;
	}

	public int getWeek() {
		return week;
	}

	public void setWeek(int week) {
		this.week = week;
	}

	public String getWeekDay() {
		return weekDay;
	}
	/**
	 * Sets weekDay
	 * @param weekDay should be the full english name for a weekday starting with an upper-case character, i.e "Tuesday" and not "tuesday"
	 */
	public void setWeekDay(String weekDay) {
		this.weekDay = weekDay;
	}

	public String getMonthString() {
		return monthString;
	}
	/**
	 * Sets monthString
	 * @param monthString should be the full english name for a month starting with an upper-case character, i.e "July" and not "july"
	 */
	public void setMonthString(String monthString) {
		this.monthString = monthString;
	}

	public String getDayMonthString() {
		return dayMonthString;
	}

	public String getWeekString() {
		return weekString;
	}
	/**
	 * Sets weekString
	 * @param weekString should be on the form "Week NN" or "Week N", where N is the week-number. Note that the first character is upper-case
	 */
	public void setWeekString(String weekString) {
		this.weekString = weekString;
	}

}
